package com.uetoken.cn.utils;

import android.text.TextUtils;

import com.blankj.utilcode.util.AppUtils;
import com.blankj.utilcode.util.EncodeUtils;
import com.blankj.utilcode.util.SPUtils;
import com.uetoken.cn.common.Constant;
import com.uetoken.cn.language.MultiLanguageUtil;
import com.uetoken.cn.network.HttpParamsSignature;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.SimpleTimeZone;
import java.util.UUID;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;

public class UrlUtils {

    private static final String ENCODING = "UTF-8";
    private static final String ISO8601_DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ss'Z'";

    /**
     * 区块链
     * 获取提现信息
     * nodeid (integer): 用户ID ,
     * purseconfigid (integer): 钱包类型 ,
     */
    public static String getUrlParamsByMap(Map<String, String> map) {
        if (map == null) {
            return "";
        }
        StringBuffer sb = new StringBuffer();
        for (Map.Entry<String, String> entry : map.entrySet()) {
            sb.append(entry.getKey() + "=" + entry.getValue());
            sb.append("&");
        }
        String s = sb.toString();
        if (s.endsWith("&")) {
            s = s.substring(0, s.length() - 1);
        }
        return s;
    }

    /**
     * @param map URL参数
     * @return Map<String, String>参数集合
     */
    public static Map<String, String> getDataParams(Map<String, String> map) {
        Map<String, String> newMap = getParamsMap(map);
        String signature = getSignatureParams("POST", newMap);
        newMap.put("Signature", signature);
        return newMap;
    }

    /**
     * 获取新组合的map参数
     *
     * @param map 变得参数
     * @return 变动参数+固定参数组合新的map参数集合
     */
    public static Map<String, String> getParamsMap(Map<String, String> map) {
        Map<String, String> newMap = new HashMap<>();
        for (String key : map.keySet()) {
            if (!TextUtils.isEmpty(map.get(key))) {
                newMap.put(key, map.get(key));
            }
        }
        //下面是公共的参数
        newMap.put("version", AppUtils.getAppVersionName());
        newMap.put("lang", MultiLanguageUtil.getInstance().getParams());
        newMap.put("sid", Constant.APPID);
        newMap.put("clientId", Constant.CLIENT_ID);
        newMap.put("token", SPUtils.getInstance(Constant.UE_TOKEN_OTHER_USER_INFO).getString(Constant.SP_GE_TUI_TOKEN, ""));
        newMap.put("accesskeyid", Constant.ACCESSKEY_ID);
        newMap.put("timestamp", formatIso8601Date(new Date()));
        newMap.put("signaturenonce", UUID.randomUUID().toString());
        return newMap;
    }

    /**
     * @param httpMethod 请求方式("GET","POST"...)字符串
     * @param parameters map参数集合
     * @return 参数集合的字符串
     */
    public static String getSignatureParams(String httpMethod, Map<String, String> parameters) {

        // 排序请求参数
        String[] sortedKeys = parameters.keySet().toArray(new String[]{});
        Arrays.sort(sortedKeys);
        String SEPARATOR = "&";
        // 构造 stringToSign 字符串
        StringBuilder stringToSign = new StringBuilder();
        stringToSign.append(httpMethod).append(SEPARATOR);
        try {
            stringToSign.append(percentEncode("/")).append(SEPARATOR);
            StringBuilder canonicalizedQueryString = new StringBuilder();
            for (String key : sortedKeys) {
                // 这里注意编码 key 和 value
                canonicalizedQueryString.append("&")
                        .append(percentEncode(key)).append("=")
                        .append(percentEncode(parameters.get(key)));
            }
            // 这里注意编码 canonicalizedQueryString
            stringToSign.append(percentEncode(canonicalizedQueryString.toString().substring(1)));
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        //将构造的参数进行签名，返回签名参数
        return signParam(stringToSign.toString());
    }

    /**
     * @param stringToSign 参数集合字符串
     * @return 参数集合字符串加密
     */
    private static String signParam(String stringToSign) {
        final String ALGORITHM = "HmacSHA1";
        final String ENCODING = "UTF-8";
        String key = Constant.ACCESSKEY_SECRECT + "&";
        Mac mac = null;
        try {
            mac = Mac.getInstance(ALGORITHM);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        try {
            mac.init(new SecretKeySpec(key.getBytes(ENCODING), ALGORITHM));
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        byte[] signData = new byte[0];
        try {
            signData = mac.doFinal(stringToSign.getBytes(ENCODING));
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        String signature = new String(EncodeUtils.base64Encode(signData));
        return encodingSignature(signature);
    }

    /**
     * @param signature
     * @return 对生成的签名参数进行编码
     */
    private static String encodingSignature(String signature) {
        String encodingSignature = "";
        try {
            encodingSignature = percentEncode(signature);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return encodingSignature;
    }

    private static String formatIso8601Date(Date date) {
        SimpleDateFormat df = new SimpleDateFormat(ISO8601_DATE_FORMAT);
        df.setTimeZone(new SimpleTimeZone(0, "GMT"));
        return df.format(date);
    }

    private static String percentEncode(String value) throws UnsupportedEncodingException {
        return value != null ? URLEncoder.encode(value, ENCODING).replace("+", "%20").replace("*", "%2A").replace("%7E", "~") : null;
    }
}
